"""
季节性差分自回归滑动平均模型
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import json
import itertools
from sklearn.metrics import mean_squared_error,r2_score


from matplotlib.pylab import style #自定义图表风格
style.use('ggplot')

# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Simhei']
# 解决坐标轴刻度负号乱码
plt.rcParams['axes.unicode_minus'] = False

#pip install statsmodels
from statsmodels.graphics.tsaplots import plot_acf,plot_pacf  #自相关图、偏自相关图
from statsmodels.tsa.stattools import adfuller as ADF #平稳性检验
from statsmodels.stats.diagnostic import acorr_ljungbox #白噪声检验
import statsmodels.api as sm #D-W检验,一阶自相关检验
from statsmodels.graphics.api import qqplot #画QQ图,检验一组数据是否服从正态分布
from statsmodels.tsa.arima.model import ARIMA

with open('../saleByTopFromSeries.json','r',encoding='utf-8') as f:
    listRS = json.load(f)
for index in range(len(listRS)):
    pyearAndMonth = listRS[index]["yearAndMonth"]
    yearAndMonth = pyearAndMonth[:42]
    psalesData = listRS[index]["salesData"]
    salesData = psalesData[:42]
    series = listRS[index]["series"]
    seriesId = listRS[index]["seriesId"]

    # 创建字典对象
    pdata = {"date": pyearAndMonth, "sale": psalesData}

    # 创建dataframe
    psale = pd.DataFrame(pdata)

    # # 转换日期数据类型
    # index = pd.DatetimeIndex(yearAndMonth)

    # 将日期设置索引值
    psale.set_index(['date'], inplace=True)

    # 转换销售量数据类型
    psale.sale = psale.sale.astype('float')

    # 判断0的个数，多于十二个0的数据不做计算
    if sum(i == '0' for i in psalesData) > 12:
        continue

    # 创建字典对象
    data = {"date": yearAndMonth, "sale": salesData}

    # 创建dataframe
    sale = pd.DataFrame(data)

    # # 转换日期数据类型
    # index = pd.DatetimeIndex(yearAndMonth)

    # 将日期设置索引值
    sale.set_index(['date'], inplace=True)

    # 转换销售量数据类型
    sale.sale = sale.sale.astype('float')

    primitiveSale = sale

    p = d = q = range(0, 2)
    pdq = list(itertools.product(p, d, q))
    pdq_x_PDQs = [(x[0], x[1], x[2], 12) for x in list(itertools.product(p, d, q))]
    a = []
    b = []
    c = []
    wf = pd.DataFrame()
    for param in pdq:
        for seasonal_param in pdq_x_PDQs:
            try:
                mod = sm.tsa.statespace.SARIMAX(primitiveSale, order=param, seasonal_order=seasonal_param,
                                                enforce_stationarity=False, enforce_invertibility=False)
                results = mod.fit()
                # print('ARIMA{}x{} - AIC:{}'.format(param, seasonal_param, results.aic))
                a.append(param)
                b.append(seasonal_param)
                c.append(results.aic)
            except:
                continue
    wf['pdq'] = a
    wf['pdq_x_PDQs'] = b
    wf['aic'] = c
    param = wf[wf['aic'] == wf['aic'].min()]
    # print(wf[wf['aic'] == wf['aic'].min()])

    mod = sm.tsa.statespace.SARIMAX(primitiveSale,
                                    order=param['pdq'].values[0],
                                    seasonal_order=param['pdq_x_PDQs'].values[0],
                                    enforce_stationarity=False,
                                    enforce_invertibility=False)
    results = mod.fit()

    # 预测
    print('未来6月的销量预测：')
    fore = results.forecast(6)


    plt.plot(pd.DatetimeIndex(psale.index), psale.sale, label="原始数据", color="b")
    plt.plot(pd.DatetimeIndex(primitiveSale.index), primitiveSale.sale, label="阉割数据", color="g")
    plt.plot(fore.index, fore.values, label="预测结果", color="r")
    plt.legend(loc="upper left")
    plt.title(series + "汽车销量预测")  # 图形标题
    plt.savefig("./img_1220/" + seriesId + 'af_sale___'+str(round(r2_score(psalesData[-6:],fore.values), 2))+'.jpg')
    plt.pause(1)
    plt.close()


